Hi! I’m Zander
, I make web things
ZUI
A CSS-first UI library with design tokens, layered architecture, and optional React, Astro, Solid, Svelte & Vue components. No build step required.
➤ zui.zander.wtf
Otter
A self-hosted bookmark manager and media tracker built for people who value privacy and ownership.
➤ otter.zander.wtfAbout me
Product engineer with 18 years of experience, specialising in front-end and design systems - building products that work well for the people who use them.
For more details on my work experience, check out my CV →
Blog
The guidance contradicts itself and almost none of it is dated, so here's a map of who says what, what the research supports, and how AGENTS.md fits in.
I extracted the search implementation I built for this site into an npm package, so you can add full-text search to your own Astro site
The site search I built last month is now a package: astro-d1-search is an Astro integration that adds full-text search backed by Cloudflare D1 to any Astro site running on the Cloudflare adapter. Build-time indexing, an injected /api/search endpoint, bm25 + recency ranking, and a searchIndex() function for server-rendered search pages — all driven by one config object.
This site now runs on the package rather than its own copy of the code, which removed about 400 lines from the repo. There are docs, a repo, and an agent skill (npx skills add mrmartineau/astro-d1-search) so Claude Code can wire it up for you.
I wrote up the whole thing in astro-d1-search: site search for Astro in one integration.
Otter now has a proper native iOS app, written in SwiftUI. No web views anywhere: browsing bookmarks and saving new ones both go through Otter’s REST API directly, with the first page of bookmarks cached to disk so the list renders instantly at launch and refreshes in the background. The difference in performance over loading the web app is enormous.
Sign-in is OAuth 2.1 with PKCE, using RFC 7591 dynamic client registration — you type your instance address and that’s it, no client ID to configure. Tokens live in a keychain group shared with the extensions.
Saving works from wherever you happen to be: the system share sheet, the + button, an otter://save?url=… deep link, or a “Save Bookmark” Shortcuts action. The Xcode project also ships a Safari web extension for saving the current page, on both iOS and macOS.
Replacing Algolia on this very website with a self-owned, full-text search API built on Cloudflare D1 and SQLite FTS5, searchable from the site itself and from Raycast
Code Notes
TILs, snippets—my digital code garden